package org.example.database.service.impl;


import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.example.database.DTO.OptimizedResumeDTO;
import org.example.database.DTO.ResumeDTO;
import org.example.database.Mapper.AdviceMapper;
import org.example.database.Mapper.RecruitmentPositionMapper;
import org.example.database.Mapper.ResumeMapper;
import org.example.database.entity.Advice;
import org.example.database.entity.RecruitmentPosition;
import org.example.database.entity.Resume;
import org.example.database.service.OllamaService;
import org.example.database.service.ResumeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ResumeServiceImpl implements ResumeService {

    @Autowired
    private ResumeMapper resumeMapper;

    @Autowired
    private OllamaService ollamaService;

    @Autowired
    private RecruitmentPositionMapper positionMapper;

    @Autowired
    private AdviceMapper adviceMapper;

    @Autowired
    private ObjectMapper objectMapper;

    private static final String OLLAMA_API_URL = "http://localhost:11434/api/generate";

    private final RestTemplate restTemplate;

    public ResumeServiceImpl() {
        this.restTemplate = new RestTemplate();
    }
    /**
     * 处理简历文件
     *
     * @param file       简历文件
     * @param studentNum
     * @return 处理后的简历信息
     */
    @Override
    public Resume processResume(MultipartFile file, Integer studentNum) throws IOException {
        String content = extractResumeText(file);
        // 2. 使用AI模型提取信息
        ResumeDTO resumeDTO = ollamaService.extractResumeInfo(content);

        // 3. 创建简历对象
        Resume resume = new Resume();
        resume.setStudentNum(studentNum);
        resume.setName(resumeDTO.getName());
        resume.setMajor(resumeDTO.getMajor());
        resume.setEducationBackground(resumeDTO.getEducationBackground());
        resume.setAcademy(resumeDTO.getAcademy());
        resume.setWorkExperience(resumeDTO.getWorkExperience());
        resume.setTimeOfGraduation(resumeDTO.getTimeOfGraduation());
        resume.setTimeOfEnrollment(resumeDTO.getTimeOfEnrollment());
        resume.setSkill(String.valueOf(resumeDTO.getSkill()));
        resume.setJobIntention(resumeDTO.getJobIntention());
        resume.setCertificate(String.valueOf(resumeDTO.getCertificate()));
        resume.setAssessmentResult(resumeDTO.getAssessmentResult());

        // 4. 保存到数据库
        resumeMapper.insert(resume);

        // 5. 生成简历评分和建议
        generateResumeAdvice(resume);

        return resume;
    }

    /**
     * 自动判断文件类型并提取文本内容
     */
    private String extractResumeText(MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        if (fileName == null) {
            throw new IllegalArgumentException("文件名为空");
        }

        if (fileName.endsWith(".pdf")) {
            try (PDDocument document = PDDocument.load(file.getInputStream())) {
                PDFTextStripper stripper = new PDFTextStripper();
                return stripper.getText(document);
            }
        } else if (fileName.endsWith(".docx")) {
            StringBuilder sb = new StringBuilder();
            try (XWPFDocument document = new XWPFDocument(file.getInputStream())) {
                List<XWPFParagraph> paragraphs = document.getParagraphs();
                for (XWPFParagraph para : paragraphs) {
                    sb.append(para.getText()).append("\n");
                }
            }
            return sb.toString();
        } else if (fileName.endsWith(".txt")) {
            return new String(file.getBytes(), StandardCharsets.UTF_8);
        } else {
            throw new UnsupportedOperationException("不支持的文件类型：" + fileName);
        }
    }

    /**
     * 生成简历评分和建议
     *
     * @param resume 简历对象
     * @return
     */


    public Advice generateResumeAdvice(Resume resume) {
        // 使用AI模型评估简历
        String prompt = String.format("""
            请对以下简历进行评估，从完整性（1分）、专业性（1分）和逻辑性（1分）三个维度进行打分，并给出具体的修改建议。
            
            简历信息：
            姓名：%s
            专业：%s
            学历背景：%s
            毕业院校：%s
            工作/实习经历：%s
            技能：%s
            求职意向：%s
            证书：%s
            毕业时间：%s
            入学时间：%s
            
            请返回JSON格式的评估结果：
            {
              "integrityScore": 完整性得分（0-1）,
              "professionalScore": 专业性得分（0-1）,
              "logicScore": 逻辑性得分（0-1）,
              "overallResult": "总体评价（优秀/良好/一般/需要改进）",
              "amendingAdvice": "具体修改建议"
            }
            """,
                resume.getName(),
                resume.getMajor(),
                resume.getEducationBackground(),
                resume.getAcademy(),
                resume.getWorkExperience(),
                resume.getSkill(),
                resume.getJobIntention(),
                resume.getCertificate(),
                resume.getTimeOfGraduation(),
                resume.getTimeOfEnrollment());

        Map<String, Object> request = new HashMap<>();
        request.put("model", "qwen3:8b");
        request.put("prompt", prompt);
        request.put("stream", false);

        Map<String, Object> response = restTemplate.postForObject(OLLAMA_API_URL, request, Map.class);
        String rawResponse = (String) response.get("response");

        try {
            // 解析AI模型返回的JSON结果
            String jsonText = generateResumeAdvice(rawResponse);
            log.info("模型原始响应内容：{}", rawResponse);
            Map<String, Object> aiResult = objectMapper.readValue(jsonText, Map.class);
            float integrityScore = Float.parseFloat(aiResult.get("integrityScore").toString());
            float professionalScore = Float.parseFloat(aiResult.get("professionalScore").toString());
            float logicScore = Float.parseFloat(aiResult.get("logicScore").toString());
            String overallResult = (String) aiResult.get("overallResult");
            String amendingAdvice = (String) aiResult.get("amendingAdvice");

            // 保存评分数据到数据库
            Advice advice = Advice.builder()
                    .resumeId(resume.getResumeId())
                    .result(overallResult)
                    .integrityScore(integrityScore)
                    .professionalScore(professionalScore)
                    .logicScore(logicScore)
                    .amendingAdvice(amendingAdvice)
                    .build();
            adviceMapper.insert(advice);
            return advice;

        } catch (Exception e) {
            log.error("解析AI模型响应失败", e);
            throw new RuntimeException("生成简历评估失败", e);
        }
    }


    /**
     * 解析json数据的方法
     * @param text
     * @return
     */
    private String generateResumeAdvice(String text) {
        // 添加extractJsonBlock方法
        Pattern pattern = Pattern.compile("\\{(?:[^{}]|\\{[^{}]*\\})*\\}", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(text);
        if (matcher.find()) {
            return matcher.group();
        }
        throw new RuntimeException("未能从模型响应中提取出 JSON 内容");
    }



    /**
     * 获取简历
     * @param resumeId
     * @return
     */
    @Override
    public Resume getResumeById(Integer resumeId) {
        return resumeMapper.selectById(resumeId);
    }

    /**
     * 生成优化后的简历
     *
     * @param resume
     * @return
     */
    @Override
    public OptimizedResumeDTO generateOptimizedResume(Resume resume) {
        // 构建提示词，要求AI模型优化简历内容
        String prompt = String.format("""
            请对以下简历内容进行优化和改进，使其更加专业和有竞争力。保持原有信息准确性的同时，优化表达方式和内容组织。
            
            简历信息：
            姓名：%s
            专业：%s
            学历背景：%s
            毕业院校：%s
            工作/实习经历：%s
            技能：%s
            求职意向：%s
            证书：%s
            毕业时间：%s
            入学时间：%s
            
            请返回JSON格式的优化结果：
            {
              "name": "姓名",
              "major": "优化后的专业描述",
              "educationBackground": "优化后的学历背景",
              "academy": "毕业院校",
              "workExperience": "优化后的工作/实习经历描述",
              "skill": "优化后的技能描述",
              "jobIntention": "优化后的求职意向",
              "certificate": "优化后的证书描述",
              "timeOfGraduation": "毕业时间",
              "timeOfEnrollment": "入学时间",
              "optimizationSuggestions": "整体优化建议"
            }
            """,
                resume.getName(),
                resume.getMajor(),
                resume.getEducationBackground(),
                resume.getAcademy(),
                resume.getWorkExperience(),
                resume.getSkill(),
                resume.getJobIntention(),
                resume.getCertificate(),
                resume.getTimeOfGraduation(),
                resume.getTimeOfEnrollment());

        // 调用AI模型进行优化
        Map<String, Object> request = new HashMap<>();
        request.put("model", "qwen3:8b");
        request.put("prompt", prompt);
        request.put("stream", false);

        Map<String, Object> response = restTemplate.postForObject(OLLAMA_API_URL, request, Map.class);
        String rawResponse = (String) response.get("response");

        try {
            // 解析AI模型返回的JSON结果
            String jsonText = generateResumeAdvice(rawResponse);
            log.info("模型优化响应内容：{}", rawResponse);
            Map<String, Object> optimizedResult = objectMapper.readValue(jsonText, Map.class);

            // 构建优化后的简历DTO
            OptimizedResumeDTO optimizedResume = OptimizedResumeDTO.builder()
                    .name((String) optimizedResult.get("name"))
                    .major((String) optimizedResult.get("major"))
                    .educationBackground((String) optimizedResult.get("educationBackground"))
                    .academy((String) optimizedResult.get("academy"))
                    .workExperience((String) optimizedResult.get("workExperience"))
                    .skill((String) optimizedResult.get("skill"))
                    .jobIntention((String) optimizedResult.get("jobIntention"))
                    .certificate((String) optimizedResult.get("certificate"))
                    .timeOfGraduation((String) optimizedResult.get("timeOfGraduation"))
                    .timeOfEnrollment((String) optimizedResult.get("timeOfEnrollment"))
                    .optimizationSuggestions((String) optimizedResult.get("optimizationSuggestions"))
                    .build();

            return optimizedResume;

        } catch (Exception e) {
            log.error("解析AI模型响应失败", e);
            throw new RuntimeException("生成优化简历失败", e);
        }
    }




    /**
     * 获取推荐职位
     * @param resume
     * @return
     */
    @Override
    public List<RecruitmentPosition> getRecommendedJobs(Resume resume) {
        // 1. 获取所有可用职位
        List<RecruitmentPosition> allPositions = positionMapper.selectAll();

        // 2. 构建提示词，要求AI模型分析简历和职位匹配度
        String prompt = String.format("""
            请分析以下简历与职位的匹配程度，考虑专业背景、技能要求、工作经验等多个维度。
            返回最匹配的职位列表（最多5个），按匹配程度从高到低排序。
            
            简历信息：
            姓名：%s
            专业：%s
            学历背景：%s
            毕业院校：%s
            工作/实习经历：%s
            技能：%s
            求职意向：%s
            证书：%s
            
            请分析以下职位并返回JSON格式的推荐结果：
            {
              "recommendedJobs": [
                {
                  "jobId": 职位ID,
                  "jobName": "职位名称"
                }
              ]
            }
            """,
                resume.getName(),
                resume.getMajor(),
                resume.getEducationBackground(),
                resume.getAcademy(),
                resume.getWorkExperience(),
                resume.getSkill(),
                resume.getJobIntention(),
                resume.getCertificate());

        // 3. 对每个职位进行分析
        List<Map<String, Object>> jobAnalysisList = new ArrayList<>();
        for (RecruitmentPosition position : allPositions) {
            String jobPrompt = prompt + "\n\n待分析职位：\n" +
                    "职位ID：" + position.getJobNumber() + "\n" +
                    "职位名称：" + position.getJobName() + "\n" +
                    "部门：" + position.getDepartment() + "\n" +
                    "学历要求：" + position.getEducationalRequirement() + "\n" +
                    "职位描述：" + position.getJobDescription();

            Map<String, Object> request = new HashMap<>();
            request.put("model", "qwen3:8b");
            request.put("prompt", jobPrompt);
            request.put("stream", false);

            Map<String, Object> response = restTemplate.postForObject(OLLAMA_API_URL, request, Map.class);
            String rawResponse = (String) response.get("response");

            try {
                String jsonText = generateResumeAdvice(rawResponse);
                Map<String, Object> result = objectMapper.readValue(jsonText, Map.class);
                jobAnalysisList.addAll((List<Map<String, Object>>) result.get("recommendedJobs"));
            } catch (Exception e) {
                log.error("解析职位匹配结果失败", e);
            }
        }

        // 4. 返回推荐职位
        return jobAnalysisList.stream()
                .limit(2)
                .map(job -> {
                    Integer jobId = (Integer) job.get("jobId");
                    return positionMapper.selectById(jobId);
                })
                .collect(Collectors.toList());
    }

}

